/*************************************************************************
    > File Name: implement_set_env.c
    > Author:		
    > Mail:		
    > Created Time: 2021年03月22日 星期一 16时44分06秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

extern char **environ;

void usage(char *progma)
{

	printf("Usage: %s arg1=x arg2=y\n", progma);

}

void show_env(void)
{
	char **ep;
	if (!environ) {
		return;
	}

	for (ep = environ; *ep != NULL; ep++) {
		puts(*ep);
	}
}

int unset_env(const char *name)
{
    extern char **environ;
    char **ep, **sp;
    size_t len;

    if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL) {
        errno = EINVAL;
        return -1;
    }

    len = strlen(name);

    for (ep = environ; *ep != NULL; )
        if (strncmp(*ep, name, len) == 0 && (*ep)[len] == '=') {

            /* Remove found entry by shifting all successive entries
               back one element */

            for (sp = ep; *sp != NULL; sp++)
                *sp = *(sp + 1);

            /* Continue around the loop to further instances of 'name' */

        } else {
            ep++;
        }

    return 0;
}

int set_env(const char *name, const char *value, int overwrite)
{
    char *es;

    if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL ||
            value == NULL) {
        errno = EINVAL;
        return -1;
    }

    if (getenv(name) != NULL && overwrite == 0)
        return 0;

    unsetenv(name);             /* Remove all occurrences */

    es = malloc(strlen(name) + strlen(value) + 2);
                                /* +2 for '=' and null terminator */
    if (es == NULL)
        return -1;

    sprintf(es, "%s=%s", name, value);

    return (putenv(es) != 0) ? -1 : 0;
}

int main(int argc, char *argv[])
{

	char *val, *name;
	if (argc != 3) {
		usage(argv[0]);
		goto err;
	}

	clearenv();

	for (int i = 1; i < argc; i ++) {
		name = argv[i];
		val = strchr(name, '=');
		if (!val) {
			usage(argv[0]);
			goto err;
		}
		*val = '\0';
		val++;
		if (set_env(name, val, 0)) {
			goto err;
		}
	}
	printf("set env from cmdline!\n");
	show_env();

	printf("unset env from cmdline %s\n", argv[2]);
	unset_env(argv[2]);
	show_env();

	return 0;
err:
	exit(-1);
}
